CUBE CONNECT Edition Help

Control statement syntax

This section describes the syntax, or components, of control statements. Topics include:

Statement tokens (%…%) and (@…@)

Any statement may contain tokens for substitution. There are two types of tokens: %…% and @…@. When the CUBE Voyager system reader routine finds a %…% token. the entire token is replaced with the value from the environment, if there is a name in the environment that matches the string between the token symbols (case insensitive). It should be noted that the environment is a copy of the environment when CUBE Voyager began. Any CUBE Voyager *SET statements will NOT have altered the environment.

When the system reader finds a @…@ token, the token is replaced with the contents of the CUBE Voyager variable that matches the string. If no matching CUBE Voyager variable is found, the token is not modified. A CUBE Voyager variable is one that has been defined within the CUBE Voyager Pilot program, or has been added via a LOG statement in a RUN program. The replacement occurs ONLY when the statement is read, and is a literal replacement.

Example

ijk = @ijk@ ; retrieve value from CUBE Voyager
xxx = @matrix.xxx@ ; retrieve value of xxx as set by prior matrix
PRINT LIST=’ijk from CUBE Voyager PILOT=’, ijk ; will be OK

Comments

There may be comments appended to any control statement/line. Comments must be preceded by a semi-colon (;). There may be any number of spaces before and/or after the semi-colon; they are ignored. If a statement is continued onto subsequent lines, each line may have comments. A semicolon (;) as the first character of a statement sets the entire statement as a comment.

Example
FILEI NETI=myfile.nam, ; I/P network
ZDATI=zonal.dat ; Zonal data
; this entire line is a comment
In the previous example, the FILEI control statement is continued because a comma follows the network filename. The statement could also have been coded as:
FILEI NETI=myfile.nam, ZDATI=zonal.dat ; I/P network, Zonal data

As a program reads each control statement, it is diagnosed, and listed to the system print file, thus providing a document for the program application. Comments are very helpful and should be used whenever it helps to clarify the application. If the first non-blank character of a data record is a semi-colon, the record is not processed. Blank lines can be used for spacing purposes. Blank lines following a line with a continuation character are ignored, and the line following the last blank line is considered as the continuation.

Null blocks

The null block is a section of the input stream that is not processed by the program; it is skipped over when the program reads the control statement. The block begins with /* and ends with */, and blocks may be nested. Therefore, care must be exercised when null blocks are used; if another /* appears before the terminating */ is read, the program assumes that there is another null block within the current one. This nesting allows the user to block out a section of the control stream even if a section of the stream already contains a null block. The rule is that each /* must have a matching */. A null block can be used to block out stream terminators and even portions of a control stream specifying other programs to be run. If a matching */ is not found, the end of the block is set to the end of file on the control stream. Hint: to run only the first portion of an input stream, place an unmatched /* record after the last desired statement.

Hint: to run only the first portion of an input stream, place an unmatched /* record after the last desired statement.

Example

FILEI NETI=myfile.nam, /* I/P network */ ZDATI=zonal.dat ; Zonal data ; ** valid, but not recommend **
FILEI NETI=ipfile.net /* FILEO NETO=opfile.net */
FILEI NETI=myfile.nam, ; I/P network
/* ZDATI=zonal.dat ; Zonal data */
FILEO ... ; will be an error, because FILEI is to be continued.

Control blocks

A control block can be used to block a control statement. The standard format for a control statement requires that the first word of the statement must be a valid control word, and must be followed by at least one key word. The statement can optionally be continued onto subsequent lines by use of a continuation character. Alternatively, a control block can be used. A control block begins with the control word, white space, and the {} character. All data up to the next {} character are considered as part of the statement. If multiple lines are used, they need not contain continuation characters. The statement will terminate with the {} character. Care must be taken: if there is no {}, the remainder of the input stream will be appended to the current statement. If the terminating {} is embedded within a literal string (‘.. {} ..’ or “.. {} ..”), or it follows a semicolon (;) on a line, it will not be recognized. Currently a control block may be on one line, but planned revisions will probably preclude this capability. There is no reason to have a control block on a single line, so it is advisable to not code them that way.

FILEI {
NETI = ... ; continuation character not required.
ZDATI = ...
}
FILEI {NETI = ... MATI = ... } ; not recommended – possible future change
FILEI {NETI = ... ; input network } ; invalid: comment precedes the {}.
FILEI {NETI = ... ; input network
} ; valid: the {} is on a separate line.

Control fields

A field is a number, or character string, that stands by itself on a control statement. In this system, fields are thought of as the characters that begin a word and continue until a field terminator, or delimiter, is detected. The field does not contain the delimiter. The standard field delimiters are blank, comma, equals sign, dash, or any mathematical operator (+-*/|&). When a field is followed by a blank, the next non-blank character (if it is one of the delimiters) is considered as the field delimiter. In many cases there need not be a specific separator; the blank will suffice. Thus, A=B is the same as A = B, which is the same as A= B. Likewise 1 2 3 4 5 is the same as 1,2,3,4,5 or 1, 2 3, 4 5.

Because many transportation-planning programs have traditionally used a dash as a field separator, that tradition is carried over to this system. Dashes do cause some ambiguity, however, because they are also the same as a minus sign. A dash is therefore used to specify ranges of values, and to specify negative values, so care must be taken. If a field is terminated by a dash, it is the beginning of a range. If a field is begun by a dash, it is a negative value, unless it could also be construed as a range. The rules applied when a dash is between fields are:

  • If the dash touches the first field, or it touches neither field, it is a range.

  • If the dash touches the second field without touching the first field, the dash is the sign for the second field.

  • If the dash touches the second field, and there is another dash between the first field and the dash, it is a range with the second field being negative.

Examples of numbers specified as single or range values

  • 1-5,1 - 5,1 -- 5 - three ways of specifying range: 1 through 5.

  • 1 -5 - value 1, and value -5.

  • 1 5, 1,5 , 1 , 5 - three ways of specifying: value 1 and value 5.

  • 1 ,-5 - error!

  • 1 , -5 - value 1 and value -5

  • 1 3 -5 - value 1 and range: 3 through 5.

  • -1 -5 - range: -1 through +5

  • -1- -5 - range: -1 through -5; descending, and could be an error.

  • -8--5 - range: -8 through -5, but doesn’t look nice.

  • -8- -5 - range: -8 through -5, but less confusing.

It should be noted that this syntax is somewhat different for numeric expression fields as noted below; ranges are invalid in such expressions. Select expressions do allow ranges for single variables, strings, and results of numeric expressions, so it is suggested that parenthesis be used to remove any ambiguities in expressions. This is described in more detail in "IF … ELSEIF … ELSE … ENDIF".

Keywords

All control information is entered by coding a keyword followed by an equals sign (=) and then the value(s) to be entered for the keyword. Keywords may sometimes specify vector data (multiple values for successive entries in a curve or array). When a vector keyword is specified, the data is entered beginning at the first location in the array. Optionally, the vector keyword may be subscripted, so that the values are loaded into the array beginning at a specified location. A subscript is specified by inclosing it within square brackets []. When a keyword is subscripted, there may be no special characters prior to the right bracket (]); the subscript must fill the space between the [].

Most keywords that are subscripted are specific to the program, and the subscript must be an integer constant. Some programs allow certain vectored keywords to have a variable as the subscript; this is usually only when the keyword is on a COMP (or similar type of statement).

Some keywords allow double subscripts to indicate a matrix of rows and columns. In such cases, there are two sets of brackets [row][column]. For example: capacity stratified by lanes (row) and spdclass (column). The row index sets the row where the data is to load and the column index sets where in the row the data loading is to begin. If there is no column designation, it is assumed to be one. One is the minimum value for rows and columns. If there is more input data than is allowed in a row, the data spills into the next row (beginning at that row’s column 1), but it will not fill beyond the end of the array. In certain cases, three-dimensional arrays are allowed, but they are rare, and will be more fully defined in the specific program documentation.

Most keywords that are subscripted are specific to the program, and the subscript must be an integer constant. Some programs allow certain vectored keywords to have a variable as the subscript; this is usually only when the keyword is on a COMP (or similar type of statement).

Some keywords allow double subscripts to indicate a matrix of rows and columns. In such cases, there are two sets of brackets [row][column]. For example: capacity stratified by lanes (row) and spdclass (column). The row index sets the row where the data is to load and the column index sets where in the row the data loading is to begin. If there is no column designation, it is assumed to be one. One is the minimum value for rows and columns. If there is more input data than is allowed in a row, the data spills into the next row (beginning at that row’s column 1), but it will not fill beyond the end of the array. In certain cases, three-dimensional arrays are allowed, but they are rare, and will be more fully defined in the specific program documentation.

Examples

LINKI= LIINKI[3]= NOX[2][7]= NOX[3]= ; single value format
VAL=10,20,30,35,40,50 ; VAL[1]=10, VAL[2]=20, ..., VAL[6]=50 VAL[55]=770,
VAL[83]=1200,1250 ; VAL[83]=1200, VAL[84]=1250
VAL(2) ; invalid, the subscript must be [2]

Subkeywords

Some keywords (internal level 2) may have further descriptive keywords (level 3) associated with them, and each of those sub keywords may possibly have another sub keyword (level 4) associated with them. Level 4 is the maximum. A level 2 keyword may be used at any time, but a level 3 keyword may be used only following a level 2, 3, or 4, keyword. A level 4 keyword may be used only following a level 3 or 4 keyword. A sub level keyword applies only to the prior higher ranking keyword. An example is the Network program FILEI statement. The layering is as follows:

Example

(1) FILEI
(2) LINKI=
(3) EXCLUDE= ; These are same level (3), and can be
(3) VAR= ; used only if LINKI has proceeded them.
(4) TYP= ; These subkeywords
(4) BEG= ; are all at
(4) LEN= ; the same level, and
(4) MIN= ; can not be specified
(4) MAX= ; unless VAR= is
LINKI=myfile, var=a, beg=1,len=5,
var=dist, beg=14, len=3,
var=street, beg=6,len=5,typ=c,
LINKI[2]=myfile2.dbf, var=a,b,dist,name; DBF file

In this example, the comma following typ=c on the third line is not necessary, since LINKI is a valid FILEI invoking keyword. The typ=c applies only to street. With the comma, the four lines form a single FILEI statement. Without the comma, they form two FILEI statements.

Keyword values and documentation descriptions

What may follow the = for a keyword depends upon the criteria for the keyword. In the documentation, each keyword description begins with a criteria list enclosed within |…|. Any of the following letters (case sensitive) within the criteria list indicate what type of data must be entered for the keyword.

  • C - Character: any valid text string, but only the first character is used.

  • D - Double: Double-precision real numbers.

  • F - Filename: filenames in a format acceptable to the operating system. If the name is to contain any special characters that may be in conflict with the system delimiters, the name must be enclosed within double quotes. (Single quotes may be used, but if the operating system allows single quotes in the filename, double quotes are required). If a filename contains a question mark (?), the ? is immediately revised to PPPP, where PPPP is the CUBE Voyager prefix that has been set by the user. In some cases, if the filename does not contain an extension (.ext), the program may want to append an appropriate extension (.NET, .MAT, .DBF, etc.). To preclude the program from appending an extension, the file name should end with a dot (.) (For example, MYFILE.)

  • I - Integer: numbers that are entered without decimal points. If a decimal point is entered, the value will be processed as the nearest integer.

  • R - Real: numbers that may contain decimal points. If the number is to be entered with a negative exponent (for example, 1.23E-2), the system reader doesn’t know if the dash is an exponent sign or a field separator. With such values, the entire field must be enclosed within ‘…’ (for example, ‘1.23E-2’). This same restriction does not apply to constants within an expression because ranges are not allowed. Real numbers are entered as single precision values: precision is restricted to the 6-7 most significant digits (system dependant).

  • ? - Boolean Response: true/false character. Programs may accept various responses depending upon the native language of the user. In English, for example, a true response could possibly be any of (Yes,1, True), and the negative response could be (No, 0, False); only the first character will be processed.

  • N - Numeric expression: expressions that will result in a number. See numeric-expressions for details of expressions.

  • s - selection expression: a special form for establishing complex selection criteria; usually IF statements. The expression must be enclosed within (…). See selection-expressions for details of expressions.

  • S - String: text string, usually used for naming or identifying something. If the string is to contain any of the delimiter characters (including space), it must be enclosed within ‘…’. If it is to contain a ‘, it must be within "…".

Other characters in the criteria list provide more information about the keyword. Possible characters and their meanings are:

  • a - Ascending order: Values must be listed in ascending order.

  • K - Trigger keyword: The program recognizes the keyword directly without specification of the control statement. Therefore, you may specify trigger keywords as the first word on a statement; the program treats the entire statement as if the first word was the appropriate control statement.

  • P - Pairs: The values may be entered as single values or as pairs of numbers (two numbers separated by a dash.)

  • V - Vector: The keyword is vectored; multiple values may be entered. An index may be appended to the keyword to indicate the loading point in the keyword array. An index should not be appended if a number does not follow V, and any index may not exceed the value of the number.

  • # - If a number follows V, it is the maximum index allowed for the keyword array. For example, V100 means the highest index may be 100.

  • * - The repetition operator * may be used to enter the same value multiple times for a V keyword. The data are loaded into successive locations in the vector.

  • [n] - If [n] follows n, the keyword is doubly dimensioned, and the [n] is the size of the second dimension. For example, V10[20] means the array referenced as the keyword has 10 rows with 20 columns each.

Expressions

Expressions are either numeric formulas or selection criteria. Selection expressions may contain embedded numeric expressions.

This section discusses:

Numeric expressions

Numeric expressions are written as traditional formulas, and contain operands separated by operators. Standard hierarchy rules are followed; computation is performed from left to right, and expressions within (…) are evaluated to a single value.

The hierarchy table for operators is as follows (with importance increasing in level):

Operator Symbol Level
Addition + 1 (in strings, "+" is a concatenator)
Subtraction - 1
Multiplication * 2
Division / 2
Modular % 2
Exponentiation ^ 3

Operators are preceded and succeeded by operands, which may be numeric constants, character constants, variables, functions with their associated arguments enclosed within (…), and sub numeric expressions enclosed within (…),

Numeric constants are entered as standard floating point numbers in the "US" format:

[ddd] [.] [ddd] [fmt[sn]ddd], where: ::

[ddd]     optional digits (0-9)
[.]       optional decimal point (a period)
[fmt]     optional e or E

No "thousands separator" or other digit grouping is accepted. Constants are entered as strings enclosed in ‘…’.

A program that deals with a variable number of matrices may have the work matrices referenced by using MW[W] or MW[W][X]. Usually, matrices are referenced within a J loop (J refers to the destination, or column, cell in the matrix), but that is not always the case. At times, it may be beneficial to use a computed variable to indicate which work matrix to reference, and/or which cell in the matrix to reference. When that format is used, it is the user’s responsibility to ensure that the computed subscripts are within the correct ranges. Unpredictable results could be obtained, or the program could fatally terminate, if the subscripts are incorrect.

Expressions are allowed in the MW index on both the left and right side of an equation, and follow these rules:

  • MW[W] - The Jth cell in work matrix W

  • MW[W][X] - The Xth cell in work matrix W

Both W and X can be a hard-coded constant, a variable, or a computational expression that will be evaluated during the execution of the statement. Most programs will detect an invalid index, and terminate with a fatal condition.

Built-in functions are predefined processes that return a value to the expression; they must be followed by one, or more, expression arguments enclosed within parenthesis (). The number of arguments must match the requirements of the function. The standard functions include (this list may be expanded over time):

Numeric functions

The following are the function name and its description.

  • ABS(x) - Absolute value

  • CmpNumRetNum(V1,OP,V2,R1,R2) - Compare number V1 to number V2 based on OP and return R1 if result is true and R2 if result is false. Valid operators OP are string and can have any of the following values:

    Equal to: ‘=’ or ‘==’

    Not Equal to: ‘!=’ or ‘<>’

    Less than or equal to: ‘<=’

    Greater than or equal to: ‘>=’

    Less than: ‘<’

    Greater than: ‘>’

    V1, V2, R1 and R2 can be numeric expressions or numeric values. This expression can be nested.

    If the arguments are expressions, the expressions must be resolved before the function is called to determine which value is returned.

  • CURRENTTIME() - This function will access the current local time in number of seconds since 1/1/1970, precision down to milliseconds.

    This function returns a double-precision floating-point number. It may in turn be passed as the value (x) to FORMATDATETIME(x,w,dec,str).

    For more on usage, see Example using CURRENTTIME() and FORMATDATETIME().

  • EXP(x) - Exponential e to the x (-103 < x < 88)

  • EXPDIST(x,m,t) Probability density (if t=0) or cumulative probability (if t>0) at x given an exponential distribution with mean m.

  • EXPINV(p,m) - Inverse of exponential cumulative function at probability p given an exponential distribution with mean m. (0 ≤ p ≥ 1).

  • GAMMADIST(x,a,b,t) - Probability density (if t=0) or cumulative probability (if t>0) at x given a gamma distribution with shape parameter a and scale parameter b. (a>0, b>0)

  • GAMMAINV(p,a,b) - Inverse of gamma cumulative function at probability p given a gamma distribution with shape parameter a and scale parameter b. (a>0, b>0, 0 ≤ p ≥ 1)

  • INLIST(n,str) - Returns 1/0 to indicate if the value of n is found/not found in any normal paired list represented in str. If str contains illegal syntax, or non-numeric values, the function will try to ignore such errors, and perform the search on only valid values. Please note that the size of str may depend upon the specific program in which INLIST is used; the PARAMETERS MAXSTRING= might be required if str is long. Str can be dynamically modified in the program.

  • INT(x) - Truncated integer value

  • LN(x) - Natural logarithm (x > 0)

  • LOG(x) - Common logarithm (x > 0)

  • LOGNORMDIST(x,m,s,t) - Probability density (if t=0) or cumulative probability (if t>0) at x if x has a lognormal distribution–that is, if LOG(x) follows a normal distribution with mean m and standard deviation s.

  • LOGNORMINV(p,m,s) Inverse of lognormal cumulative function at probability p given a lognormal distribution–that is, the logarithms of values follow a normal distribution with mean m and standard deviation s. (0 ≤ p ≥ 1)

  • MAX(x,y,…) - Maximum value from the list

  • MIN(x,y,…) - Minimum value from the list

  • NORMDIST(x,m,s,t) - Probability density (if t=0) or cumulative probability (if t>0) at x given a normal distribution with mean m and standard deviation s.

  • NORMINV(p,m,s) - Inverse of normal cumulative function at probability p given a normal distribution with mean m and standard deviation s. (0 ≤ p ≥ 1)

  • POISSONDIST(x,v,t) - Probability density (if t=0) or cumulative probability (if t>0) of x occurrences given a Poisson distribution with mean and variance v.

  • POISSONINV(x,v) - Inverse of Poisson cumulative function at probability p given a Poisson distribution with mean and variance v. (0 ≤ p ≥ 1)

  • POW(x,y) - Power (x=base, y=exponent)

  • RAND() - Return a random floating point number between 0 and < 1

  • RANDOM(n) - Return a random integer between 0 and n-1, n is an integer between 1 and 2147483647

  • RANDSEED(n) - Initialize the random number generator with n, where n is an integer between 1 and 2147483647, so a repeatable series of random numbers can be generated from the rand() and random() functions.

  • ROUND(x) - Rounded integer value

  • SQRT(x) - Square root (x > 0)

Trig functions

Note: Trig functions are applied to values that are in degrees. To convert radians to degrees:
Degrees=Radians\*180/ð
  • ARCCOS(x) - Returns the ARCCOS of x.

  • ARCSIN(x) - Returns the ARCSIN (inverse SIN) of x.

    Example VAR2=ARCSIN(0.5) would return a value of 30.

    ARCSIN(SIN(x))=x

  • ARCTAN(X) - Returns the ARCTAN of x.

  • COS(x) - Returns the COS of x.

  • SIN(x) - Returns the SIN of x where x is in degrees.

    Example VAR1=SIN(30) would return a value of 0.5.

  • TAN(x) - Returns the TAN of x.

Lookup functions

Lookup functions are defined by a LOOKUP control statement. The statement must contain the source of the lookup data, the name to give the function, and optional parameters to control the actual lookup of data. See "LOOKUP" for a details about the control statement.

Each program may have a list of functions that are unique to the specific program. Those functions will be described with the specific program documentation. In some cases, the user will be allowed to define specific functions for use by the program. Functions that look up a value in an array or in a set of curves are examples of user functions.

Examples of valid expressions

x+1
(1.5/distance) + (sqrt(AreaType)*abs(FacilityType]) )
Street + ',' + City + DUPSTR(' ',3) SUBSTR(street,4,6)
FORMAT(volume,8,2,',')
STRPOS('cd','abcde')
INLIST(32, '10-15,25,31-35')
CmpNumRetNum(V1,'>=',V2,V1-V2,V2-V1)

String expressions

String expressions result in string values. String values are specified between single quotes (e.g., ‘abcde’). If a sting contains a single quote character, those strings should be enclosed inside back quotes (e.g., 'abc’de`). Character/ String functions can be used in the expression.

Note: str is either a character constant ‘…’, or a character variable
  • DELETESTR(s1,n1,n2) - Deletes n2 characters in s1 starting at n1 (1 is the first character); if n1 or n2 is < 1, then return s1.

  • DUPSTR(str,n) - Duplicates str n times; result must be less than 100 chars.

  • FORMAT(x,w,dec,str) - Formats number (x) with width=*w*, decimals=*dec*, format=*str*. The str pattern can contain any characters, but will only be used if it contains any single, or string of, m, d, or y characters. When there are one or more m, d, or y characters in the pattern, it causes x (first argument) to be treated as a date value in the format of yyyymmdd, and its corresponding month, day, year elements formatted in place of the m, d, or y characters. Width (w) is the maximum length of the resulting string and must be less than or equal to 40. Single m, d, or y characters mean single digit or double digits depending on the value. Two or more of the same special characters mean formatting to 2 digits with leading zero if needed.

    The only exception is for year, where yy means 2 digit year; anything else will be substituted with a 4-digit year.

    For example: yy/mm/dd will result in 07/02/13 if x=20070213. abc m:d:y would result in "abc 2/13/2007". If multiple occurrences of any of the y, m, or d occur, the result will contain multiple value substitutions. dd/mm/yy abcm will result in “13/02/07 abc2”.

  • FORMATDATETIME(x,w,dec,str) This function formats a date/time value (x, which can be returned from the CURRENTTIME() function) according to the formatstring (str). The result is a string.

    Width (w) is the maximum length of the resulting string and must be less than or equal to 40. Dec is the number of decimal places to display in the seconds value. The formatstring (str) is a string that provides a template for the resulting string. It can contain any characters, but any single, or string of, y, m, d, h, n or s will be substituted with the year, month, day, hour, minute and second values, respectively. Single character means single digit or double digits depending on the value. Two or more of the same special characters mean formatting to 2 digits with leading zero if needed.

    There are two exceptions to this rule. For year, yy means 2 digit year; anything else will be substituted with a 4-digit year. For hour, three or more h characters together mean printing the total number of hours in the datetime value. This form is useful when printing elapsed time between 2 datetime values but should not be used when printing a real date since it will be the number of hours since January 1, 1970.

    For more on usage, see Example using CURRENTTIME() and FORMATDATETIME().

  • INSERTSTR(s1,s2,n) - Inserts s1 into s2 at n; if n < 2, return s1*+*s2; if n > length of s2, return s2*+*s1.

  • LEFTSTR(s1,n) - Returns n characters from the left side of s1; if the length of s1 is less than n, or n is < 0, returns s1.

  • LTRIM(str) - Deletes leading spaces from str.

  • REPLACESTR(s1,s2,s3,n) - Replaces n occurrences of s2 with s3 in s1, where n is the number of replacements, 0 means all; if n < 0, then no replacements, returns s1.

  • REPLACESTRIC(s1,s2,s3,n) - Same as REPLACESTR above, but ignores case when searching for s2 within s1.

  • REVERSESTR(s1) - Reverses s1.

  • RIGHTSTR(s1,n) - Returns n characters from the right side of s1; if the length of s1 is less than n, or n is < 0, return s1.

  • STR(v,w,d) - Converts the variable v to a string that is w characters wide, with d decimal places. w must be less than 30, and d less than w-2.

  • STRLEN(str) - Returns the length of str.

  • STRLOWER(str) - Sets str to lowercase for immediate use; str is not permanently changed.

  • STRPOS(str,str2) - Returns the position in str2 where str begins. If str does not exist in str2, returns 0. Both strings are case sensitive.

  • STRPOSEX(s1,s2,n1) - Returns the position of s1 in s2, but starts the search from position n1 in s2 instead of from the beginning of s2.

    Returns 0 if not found; if n1 < 1 or n1 > length of s2, returns 0.

  • STRUPPER(str) - Sets str to uppercase for immediate use; str is not permanently changed.

  • SUBSTR(str,b,n) - Extracts a substring from str, beginning at position b, and continuing for n characters. b must be greater than 0.

    Returns an empty string if b is less than 1, if n is less than 1, if the length of str is less than 1, or if b is greater than the length of str.

  • TRIM(str) - Deletes trailing spaces from str.

  • VAL(str) - Returns the numeric value contained in str.

Example using CURRENTTIME() and FORMATDATETIME()

StartTime=currenttime()
SLEEP  TIME=1.234
EndTime=currenttime()
LowETime1 = EndTime - StartTime
; LowTime, HighTime are other DateTime values
; LowETime2, HighETime are other elapse time values

print list=' Current Date/Time=',formatdatetime(currenttime(),40,2,' yyyy-mm-dd hh:mm:ss')

print list=' Low    Date/Time=',formatdatetime( LowTime,40,3,' yyyy-mm-dd yy-m-d'),
                               formatdatetime( LowTime,40,3,' hh:nn:ss h:n:s'),
                               formatdatetime( LowTime,40,3,' hhh:nn:ss')
print list=' High   Date/Time=',formatdatetime(HighTime,40,3,' yyyy-mm-dd yy-m-d'),
                               formatdatetime(HighTime,40,3,' hh:nn:ss h:n:s'),
                               formatdatetime(HighTime,40,3,' hhh:nn:ss')
print list=' Low    Elapse Time=',formatdatetime( LowETime1,40,2,' hhh:nn:ss')
print list=' Low    Elapse Time=',formatdatetime( LowETime2,40,2,' hhh:nn:ss')
print list=' High   Elapse Time=',formatdatetime(HighETime ,40,2,' hhh:nn:ss')

 
	 

Result:

Current Date/Time= 2013-07-23 20:07:17.72
Low   Date/Time= 2013-02-03 13-2-3 04:07:09.485 4:7:9.485 377748:07:09.485
High  Date/Time= 2013-11-20 13-11-20 13:27:49.485 13:27:49.485 384717:27:49.485
Low   Elapse Time= 000:00:01.23
Low   Elapse Time= 004:05:06.79
Hight Elapse Time= 098:17:56.79

Selection Expressions

Selection expressions are used to specify criteria for selecting something. The expression is always enclosed within (…), and, when evaluated, results in a single true or false value. The syntax is similar to standard C language, but there are some exceptions. The expression may contain nested and/or a series of comparisons. The following comparison operators are used to determine the relationship between the expressions on either side of the operator (the left expression is A, and the right expression is B).

  • A = B - A equals B

  • A == B - A equals B

  • A != B - A is not equal to B

  • A >= B - A is greater than, or equal to B

  • A <= B - A is less than, or equal to B

  • A > B - A is greater than B

  • A < B - A is less than B

  • A <> B - A is not equal to B

With the = operator, B may be expressed as a series of values, and/or ranges. For example: I=1-5,15,30-99,212 means if I is 15, or 212, or falls within any of the ranges.

A or B can be a numeric expression enclosed within (…). For example:

 (a+b)/3*k)=0.5-1.9,27.2)

Further, ranges are supported only with the = operator. To exclude certain ranges, use the not (!) operator, such as !(I=2-16). For example, to exclude indices 2 through 16, the following two expressions are incorrect (resulting in checking if variable not equal to -14):

IF (variable != 2-16)
  ...
; Incorrect

IF (variable <> 2-16)
  ...
; Incorrect

The correct syntax is:

IF (!(variable = 2-16))
 ...

The range equal operator also works with strings, such as Name='S','U','X'-'Z'. String comparison is based on the ASCII code value of each character and is done from the left to right until the right-side string is exhausted. In other words, the number of characters compared is the string length on the right side. For example,

('abcde' = 'ab') is equivalent to ('ab' = 'ab'), which is true.

On the other hand, ( 'ab' = 'abcde') is false.

For a full length string comparison (exact match), compare both ways as below:

(('abcde'='ab') & ('ab'='abcde'))

One should never use an empty or null string on the right side of a comparison expression. It will always be true for equality comparison and false for other types of comparisons.

Since a blank, ' ' , is less than any printable character in ASCII code value, we can check if a text field is not empty using the following expression:
(LTrim(TextFld) > ' ')

Comparisons can be logically combined with other comparisons by using the AND operator (&&) or the OR operator (||). When logical combinations are made, it is wise to enclose them within (…); it is not always necessary, but it helps to eliminate ambiguity. A comparison enclosed within (…) can be preceded with the NOT operator (!) to cause the comparison result to be inverted. For example: !(i=5-10,12) means if I is not within the 5-10 range, nor is it equal to 12. AND and OR can currently be specified as single & and |, but this could change in the future.

Example of complex selection

( (i=1-10,37 && j=150,201-299) || (j=1-10,37 && i=150-201-299) ||
( (I=j & !(i=87-100,203) ) || ((a+sqrt(5*j)) >= (j + sqrt(6/a)) ) ))

Examples of keyword variables

int = 1
float = 1.35, 1.23E2
name=abcde, 'this is a name'
NETI=?2005.net,          ; expands to PPPP2005.net (prefix = PPPP)
     "d:\test\alta\myfile.ext",
     ..\subd?\ALTA?.net ; expands to ..\SUBDPPPP\ALTAPPPP.NET

Examples of expressions

n+1
(1.5/i) + (sqrt(MW[3])*abs(MW[m][j-1]) )
Street + ',' + City + DUPSTR(".-",3) SUBSTR(street,4,6)
Inlist(I,'1-5,99,888-993,5002,6,13')
Inlist((k*2+j), CBD) ; CBD must be a string variable
Randseed(12345)
Rand()
Random(I) ; if (I<2) will return 0.

Variable naming convention (general syntax)

Variables used in expressions must have a valid name. There are some basic rules that must be followed in assigning a name to a variable. Some programs might relax the rules a bit, but to prevent any problems, the following rules should be adhered to.

  • Length: - Any reasonable length; network variables may not exceed 15 characters. If a database file (.dbf) is to be written, the program will truncate the name to 10 characters (the maximum for the dbf).

  • Valid Characters: - A-Z, a-z, 0-9, _$#@

  • Case: - Insensitive

  • First Character: - Any of the valid characters, except 0-9

  • Temporary Variables: - Convention is to use underscore "_" as the first character.

Variables are also used to reference items specific to a program. In a network-processing program, they could reference the variables associated with a network. In a matrix program, they could reference certain matrices. They also may reference variables defined specifically for the program (that is, I, J, M, etc.), or variables defined by the user in a prior assignment control statement. Usually, variable names can be most any length, but if the variable is to be associated with an input or output file, its length must be restricted to no more than 15 characters. If a file variable is to be referenced directly, it must be preceded with a prefix to indicate which file to use.

Input file variable prefixes are always in the format ‘TI.#.’, where:

  • T - File type (L=Link, N=Node, M=Matrix, Z=ZonalData).

  • I - Indicates Input

  • # - Index (explicit or implied) number of the file type named on a FILEI control statement.

The possible filename variables formats (illustrated by example) are:

  • MI.3.varname - Refers to the matrix named varname found on the file designated by MATI[3]= on the FILEI control statement. If varname is a number, it refers to a relative matrix on the file.

  • NI.3.varname - Refers to the variable named varname found in the node portion of the network file designated by NETI[3]= on the FILEI control statement.

  • LI.2.varname - Refers to the variable named varname found in the link portion of the network file designated by NETI[2]= on the FILEI control statement.

  • ZI.5.varname - Refers to the array named varname generated by the file designated by ZDATI[5]= on the FILEI control statement. Zonal data are read into zonal arrays; each variable is an array with zones cells. Usually, the reference to a zonal value would also include a subscript; for example, ZI.5.POP[I].

Note: LI.name and NI.name are used when there is only one NETI allowed in the program (currently applies to only the Highway program).